const FULFILLED = 'fulfilled'; //成功
const REJECTED = 'rejected'; //失败
const PENDING = 'pending'; //等待

class MyPromise{
    #state = PENDING; //加上#不希望外面访问到
    #value = undefined;
    #callbacks = [];
    
    #changeState(state,value){ //改变状态时调用
        if(this.#state != PENDING)return //保证状态只能改变一次
        this.#state = state;
        this.#value = value;
        this.#runCallbacks();//改变状态时执行一次回调函数数组中的函数
    }

    #runCallbacks(){
        this.#runMicroTask(() => {
            while(this.#callbacks.length > 0){
                //这里的resolve和reject是then返回的promise的resolve和reject,调用时需要分三种情况
                const {onfulFilledCallback,onRejectedCallback,resolve,reject} = this.#callbacks.shift();
                if(this.#state === FULFILLED){
                    this.#runOne(onfulFilledCallback,resolve,reject)
                }
                if(this.#state === REJECTED){
                    this.#runOne(onRejectedCallback,resolve,reject)
                }
            }
        });
    }

    #isPromise(value){ //用来判断是否符合promise的A+规范

        //判断是否是promise的标准: 不为空,是对象或者函数,并且有一个then方法,then方法是一个函数
       if(value !==null && (typeof value === 'object' || typeof value === 'function') && typeof value.then === 'function'){
        return true
       }
       return false
    }

    #runMicroTask(fn){ //用来执行微任务
        if(typeof process === 'object' && typeof process.nextTick === 'function'){
            process.nextTick(fn)
        }else if(typeof MutationObserver === 'function'){
            const observer = new MutationObserver(fn)
            observer.observe(document.body,{
                attributes:true
            })
            observer.disconnect()
        }else{
            setTimeout(fn,0)
        }
    }

    #runOne(callback,resolve,reject){ //执行每一个回调函数时的具体操作:这里涉及到不同状态执行什么回调以及当前promise调用then返回的promise状态
        if(typeof callback != 'function'){//情况1.传入的不是一个回调函数,穿透,then的状态和当前的promise状态保持一致
            const settled = this.#state === FULFILLED ? resolve : reject
            settled(this.#value)//并且参数是当前的value或者reason,改变then返回的promise状态
            return
        }
        //情况2.如果传入的是一个函数,就调用函数,并且将返回的结果作为参数,传递给resolve或者reject
        try{
            const data = callback(this.#value)//调用回调函数,并且将返回的结果作为参数,传递给resolve或者reject
            if(this.#isPromise(data)){
                data.then(resolve,reject)//情况3.如果返回的是一个promise,则直接调用then,这里的原因是因为下一个then需要等待这个promise的resolve或者reject
                //至于这个then的返回值,则是由return Promise((value)=>{xxxxx}) 来决定的
            }else{
                resolve(data)//只要是函数的话,不报错,就调用resolve
            }
        }catch(error){
            reject(error)//如果传入的回调函数报错了,就调用reject
        }
    }

  

    constructor(executor){
        const resolve = (value)=>{//为什么不将这个函数放在原型上,而是每次创建新的promise的时候都要创建两个函数
            this.#changeState(FULFILLED,value)
        }
        const reject = (reason)=>{//原因:因为函数需要用到当前promise的一些东西,this的指向由调用者决定,因为调用resolve是在外面调用的,会造成this指向错误
            this.#changeState(REJECTED,reason)
        
        }

        try{
            executor(resolve,reject) //同步执行,在构造器中直接调用这个传入的函数
        }catch(error){
            reject(error) //如果执行器中抛出错误,则直接调用reject,只能捕获到同步的错误
        }
    
    }

    then(onfulFilledCallback,onRejectedCallback){
        return new MyPromise((resolve,reject)=>{ //返回一个promise
            this.#callbacks.push({
                onfulFilledCallback,
                onRejectedCallback,
                resolve,
                reject
            })
            this.#runCallbacks();
        })
    }
}


const p =new MyPromise((resolve,reject)=>{
    resolve('success')
})

p.then(res=>{
    console.log(res)
    return new MyPromise((resolve,reject)=>{
        reject('error')
    }).then(111)
}).then(res=>{
    console.log(res)
},reason=>{
    console.log(reason)
})